home *** CD-ROM | disk | FTP | other *** search
/ Ultra Pack / UltraComputing Partner Applications.iso / SunLabs / tclTK / src / tk4.0 / tkCanvImg.c < prev    next >
C/C++ Source or Header  |  1995-04-23  |  19KB  |  674 lines

  1. /* 
  2.  * tkCanvImg.c --
  3.  *
  4.  *    This file implements image items for canvas widgets.
  5.  *
  6.  * Copyright (c) 1994 The Regents of the University of California.
  7.  * Copyright (c) 1994 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  */
  12.  
  13. static char sccsid[] = "@(#) tkCanvImg.c 1.11 95/04/23 16:06:27";
  14.  
  15. #include <stdio.h>
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. #include "tkCanvas.h"
  19.  
  20. /*
  21.  * The structure below defines the record for each image item.
  22.  */
  23.  
  24. typedef struct ImageItem  {
  25.     Tk_Item header;        /* Generic stuff that's the same for all
  26.                  * types.  MUST BE FIRST IN STRUCTURE. */
  27.     Tk_Canvas canvas;        /* Canvas containing the image. */
  28.     double x, y;        /* Coordinates of positioning point for
  29.                  * image. */
  30.     Tk_Anchor anchor;        /* Where to anchor image relative to
  31.                  * (x,y). */
  32.     char *imageString;        /* String describing -image option (malloc-ed).
  33.                  * NULL means no image right now. */
  34.     Tk_Image image;        /* Image to display in window, or NULL if
  35.                  * no image at present. */
  36. } ImageItem;
  37.  
  38. /*
  39.  * Information used for parsing configuration specs:
  40.  */
  41.  
  42. static Tk_ConfigSpec configSpecs[] = {
  43.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  44.     "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  45.     {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
  46.     (char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK},
  47.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  48.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tk_CanvasTagsOption},
  49.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  50.     (char *) NULL, 0, 0}
  51. };
  52.  
  53. /*
  54.  * Prototypes for procedures defined in this file:
  55.  */
  56.  
  57. static void        ImageChangedProc _ANSI_ARGS_((ClientData clientData,
  58.                 int x, int y, int width, int height, int imgWidth,
  59.                 int imgHeight));
  60. static int        ImageCoords _ANSI_ARGS_((Tcl_Interp *interp,
  61.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  62.                 char **argv));
  63. static int        ImageToArea _ANSI_ARGS_((Tk_Canvas canvas,
  64.                 Tk_Item *itemPtr, double *rectPtr));
  65. static double        ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  66.                 Tk_Item *itemPtr, double *coordPtr));
  67. static void        ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas,
  68.                 ImageItem *imgPtr));
  69. static int        ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp,
  70.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  71.                 char **argv, int flags));
  72. static int        CreateImage _ANSI_ARGS_((Tcl_Interp *interp,
  73.                 Tk_Canvas canvas, struct Tk_Item *itemPtr,
  74.                 int argc, char **argv));
  75. static void        DeleteImage _ANSI_ARGS_((Tk_Canvas canvas,
  76.                 Tk_Item *itemPtr, Display *display));
  77. static void        DisplayImage _ANSI_ARGS_((Tk_Canvas canvas,
  78.                 Tk_Item *itemPtr, Display *display, Drawable dst,
  79.                 int x, int y, int width, int height));
  80. static void        ScaleImage _ANSI_ARGS_((Tk_Canvas canvas,
  81.                 Tk_Item *itemPtr, double originX, double originY,
  82.                 double scaleX, double scaleY));
  83. static void        TranslateImage _ANSI_ARGS_((Tk_Canvas canvas,
  84.                 Tk_Item *itemPtr, double deltaX, double deltaY));
  85.  
  86. /*
  87.  * The structures below defines the image item type in terms of
  88.  * procedures that can be invoked by generic item code.
  89.  */
  90.  
  91. Tk_ItemType tkImageType = {
  92.     "image",                /* name */
  93.     sizeof(ImageItem),            /* itemSize */
  94.     CreateImage,            /* createProc */
  95.     configSpecs,            /* configSpecs */
  96.     ConfigureImage,            /* configureProc */
  97.     ImageCoords,            /* coordProc */
  98.     DeleteImage,            /* deleteProc */
  99.     DisplayImage,            /* displayProc */
  100.     0,                    /* alwaysRedraw */
  101.     ImageToPoint,            /* pointProc */
  102.     ImageToArea,            /* areaProc */
  103.     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
  104.     ScaleImage,                /* scaleProc */
  105.     TranslateImage,            /* translateProc */
  106.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  107.     (Tk_ItemCursorProc *) NULL,        /* icursorProc */
  108.     (Tk_ItemSelectionProc *) NULL,    /* selectionProc */
  109.     (Tk_ItemInsertProc *) NULL,        /* insertProc */
  110.     (Tk_ItemDCharsProc *) NULL,        /* dTextProc */
  111.     (Tk_ItemType *) NULL        /* nextPtr */
  112. };
  113.  
  114. /*
  115.  *--------------------------------------------------------------
  116.  *
  117.  * CreateImage --
  118.  *
  119.  *    This procedure is invoked to create a new image
  120.  *    item in a canvas.
  121.  *
  122.  * Results:
  123.  *    A standard Tcl return value.  If an error occurred in
  124.  *    creating the item, then an error message is left in
  125.  *    interp->result;  in this case itemPtr is left uninitialized,
  126.  *    so it can be safely freed by the caller.
  127.  *
  128.  * Side effects:
  129.  *    A new image item is created.
  130.  *
  131.  *--------------------------------------------------------------
  132.  */
  133.  
  134. static int
  135. CreateImage(interp, canvas, itemPtr, argc, argv)
  136.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  137.     Tk_Canvas canvas;            /* Canvas to hold new item. */
  138.     Tk_Item *itemPtr;            /* Record to hold new item;  header
  139.                      * has been initialized by caller. */
  140.     int argc;                /* Number of arguments in argv. */
  141.     char **argv;            /* Arguments describing rectangle. */
  142. {
  143.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  144.  
  145.     if (argc < 2) {
  146.     Tcl_AppendResult(interp, "wrong # args:  should be \"",
  147.         Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
  148.         itemPtr->typePtr->name, " x y ?options?\"",
  149.         (char *) NULL);
  150.     return TCL_ERROR;
  151.     }
  152.  
  153.     /*
  154.      * Initialize item's record.
  155.      */
  156.  
  157.     imgPtr->canvas = canvas;
  158.     imgPtr->anchor = TK_ANCHOR_CENTER;
  159.     imgPtr->imageString = NULL;
  160.     imgPtr->image = NULL;
  161.  
  162.     /*
  163.      * Process the arguments to fill in the item record.
  164.      */
  165.  
  166.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
  167.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &imgPtr->y)
  168.         != TCL_OK)) {
  169.     return TCL_ERROR;
  170.     }
  171.  
  172.     if (ConfigureImage(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
  173.     DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  174.     return TCL_ERROR;
  175.     }
  176.     return TCL_OK;
  177. }
  178.  
  179. /*
  180.  *--------------------------------------------------------------
  181.  *
  182.  * ImageCoords --
  183.  *
  184.  *    This procedure is invoked to process the "coords" widget
  185.  *    command on image items.  See the user documentation for
  186.  *    details on what it does.
  187.  *
  188.  * Results:
  189.  *    Returns TCL_OK or TCL_ERROR, and sets interp->result.
  190.  *
  191.  * Side effects:
  192.  *    The coordinates for the given item may be changed.
  193.  *
  194.  *--------------------------------------------------------------
  195.  */
  196.  
  197. static int
  198. ImageCoords(interp, canvas, itemPtr, argc, argv)
  199.     Tcl_Interp *interp;            /* Used for error reporting. */
  200.     Tk_Canvas canvas;            /* Canvas containing item. */
  201.     Tk_Item *itemPtr;            /* Item whose coordinates are to be
  202.                      * read or modified. */
  203.     int argc;                /* Number of coordinates supplied in
  204.                      * argv. */
  205.     char **argv;            /* Array of coordinates: x1, y1,
  206.                      * x2, y2, ... */
  207. {
  208.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  209.     char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
  210.  
  211.     if (argc == 0) {
  212.     Tcl_PrintDouble(interp, imgPtr->x, x);
  213.     Tcl_PrintDouble(interp, imgPtr->y, y);
  214.     Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
  215.     } else if (argc == 2) {
  216.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
  217.         || (Tk_CanvasGetCoord(interp, canvas, argv[1],
  218.             &imgPtr->y) != TCL_OK)) {
  219.         return TCL_ERROR;
  220.     }
  221.     ComputeImageBbox(canvas, imgPtr);
  222.     } else {
  223.     sprintf(interp->result,
  224.         "wrong # coordinates:  expected 0 or 2, got %d", argc);
  225.     return TCL_ERROR;
  226.     }
  227.     return TCL_OK;
  228. }
  229.  
  230. /*
  231.  *--------------------------------------------------------------
  232.  *
  233.  * ConfigureImage --
  234.  *
  235.  *    This procedure is invoked to configure various aspects
  236.  *    of an image item, such as its anchor position.
  237.  *
  238.  * Results:
  239.  *    A standard Tcl result code.  If an error occurs, then
  240.  *    an error message is left in interp->result.
  241.  *
  242.  * Side effects:
  243.  *    Configuration information may be set for itemPtr.
  244.  *
  245.  *--------------------------------------------------------------
  246.  */
  247.  
  248. static int
  249. ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
  250.     Tcl_Interp *interp;        /* Used for error reporting. */
  251.     Tk_Canvas canvas;        /* Canvas containing itemPtr. */
  252.     Tk_Item *itemPtr;        /* Image item to reconfigure. */
  253.     int argc;            /* Number of elements in argv.  */
  254.     char **argv;        /* Arguments describing things to configure. */
  255.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  256. {
  257.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  258.     Tk_Window tkwin;
  259.     Tk_Image image;
  260.  
  261.     tkwin = Tk_CanvasTkwin(canvas);
  262.     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc,
  263.         argv, (char *) imgPtr, flags) != TCL_OK) {
  264.     return TCL_ERROR;
  265.     }
  266.  
  267.     /*
  268.      * Create the image.  Save the old image around and don't free it
  269.      * until after the new one is allocated.  This keeps the reference
  270.      * count from going to zero so the image doesn't have to be recreated
  271.      * if it hasn't changed.
  272.      */
  273.  
  274.     if (imgPtr->imageString != NULL) {
  275.     image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
  276.         ImageChangedProc, (ClientData) imgPtr);
  277.     if (image == NULL) {
  278.         return TCL_ERROR;
  279.     }
  280.     } else {
  281.     image = NULL;
  282.     }
  283.     if (imgPtr->image != NULL) {
  284.     Tk_FreeImage(imgPtr->image);
  285.     }
  286.     imgPtr->image = image;
  287.     ComputeImageBbox(canvas, imgPtr);
  288.     return TCL_OK;
  289. }
  290.  
  291. /*
  292.  *--------------------------------------------------------------
  293.  *
  294.  * DeleteImage --
  295.  *
  296.  *    This procedure is called to clean up the data structure
  297.  *    associated with a image item.
  298.  *
  299.  * Results:
  300.  *    None.
  301.  *
  302.  * Side effects:
  303.  *    Resources associated with itemPtr are released.
  304.  *
  305.  *--------------------------------------------------------------
  306.  */
  307.  
  308. static void
  309. DeleteImage(canvas, itemPtr, display)
  310.     Tk_Canvas canvas;            /* Info about overall canvas widget. */
  311.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  312.     Display *display;            /* Display containing window for
  313.                      * canvas. */
  314. {
  315.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  316.  
  317.     if (imgPtr->imageString != NULL) {
  318.     ckfree(imgPtr->imageString);
  319.     }
  320.     if (imgPtr->image != NULL) {
  321.     Tk_FreeImage(imgPtr->image);
  322.     }
  323. }
  324.  
  325. /*
  326.  *--------------------------------------------------------------
  327.  *
  328.  * ComputeImageBbox --
  329.  *
  330.  *    This procedure is invoked to compute the bounding box of
  331.  *    all the pixels that may be drawn as part of a image item.
  332.  *    This procedure is where the child image's placement is
  333.  *    computed.
  334.  *
  335.  * Results:
  336.  *    None.
  337.  *
  338.  * Side effects:
  339.  *    The fields x1, y1, x2, and y2 are updated in the header
  340.  *    for itemPtr.
  341.  *
  342.  *--------------------------------------------------------------
  343.  */
  344.  
  345.     /* ARGSUSED */
  346. static void
  347. ComputeImageBbox(canvas, imgPtr)
  348.     Tk_Canvas canvas;            /* Canvas that contains item. */
  349.     ImageItem *imgPtr;            /* Item whose bbox is to be
  350.                      * recomputed. */
  351. {
  352.     int width, height;
  353.     int x, y;
  354.  
  355.     x = imgPtr->x + 0.5;
  356.     y = imgPtr->y + 0.5;
  357.  
  358.     if (imgPtr->image == None) {
  359.     imgPtr->header.x1 = imgPtr->header.x2 = x;
  360.     imgPtr->header.y1 = imgPtr->header.y2 = y;
  361.     return;
  362.     }
  363.  
  364.     /*
  365.      * Compute location and size of image, using anchor information.
  366.      */
  367.  
  368.     Tk_SizeOfImage(imgPtr->image, &width, &height);
  369.     switch (imgPtr->anchor) {
  370.     case TK_ANCHOR_N:
  371.         x -= width/2;
  372.         break;
  373.     case TK_ANCHOR_NE:
  374.         x -= width;
  375.         break;
  376.     case TK_ANCHOR_E:
  377.         x -= width;
  378.         y -= height/2;
  379.         break;
  380.     case TK_ANCHOR_SE:
  381.         x -= width;
  382.         y -= height;
  383.         break;
  384.     case TK_ANCHOR_S:
  385.         x -= width/2;
  386.         y -= height;
  387.         break;
  388.     case TK_ANCHOR_SW:
  389.         y -= height;
  390.         break;
  391.     case TK_ANCHOR_W:
  392.         y -= height/2;
  393.         break;
  394.     case TK_ANCHOR_NW:
  395.         break;
  396.     case TK_ANCHOR_CENTER:
  397.         x -= width/2;
  398.         y -= height/2;
  399.         break;
  400.     }
  401.  
  402.     /*
  403.      * Store the information in the item header.
  404.      */
  405.  
  406.     imgPtr->header.x1 = x;
  407.     imgPtr->header.y1 = y;
  408.     imgPtr->header.x2 = x + width;
  409.     imgPtr->header.y2 = y + height;
  410. }
  411.  
  412. /*
  413.  *--------------------------------------------------------------
  414.  *
  415.  * DisplayImage --
  416.  *
  417.  *    This procedure is invoked to draw a image item in a given
  418.  *    drawable.
  419.  *
  420.  * Results:
  421.  *    None.
  422.  *
  423.  * Side effects:
  424.  *    ItemPtr is drawn in drawable using the transformation
  425.  *    information in canvas.
  426.  *
  427.  *--------------------------------------------------------------
  428.  */
  429.  
  430. static void
  431. DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height)
  432.     Tk_Canvas canvas;            /* Canvas that contains item. */
  433.     Tk_Item *itemPtr;            /* Item to be displayed. */
  434.     Display *display;            /* Display on which to draw item. */
  435.     Drawable drawable;            /* Pixmap or window in which to draw
  436.                      * item. */
  437.     int x, y, width, height;        /* Describes region of canvas that
  438.                      * must be redisplayed (not used). */
  439. {
  440.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  441.     short drawableX, drawableY;
  442.  
  443.     if (imgPtr->image == NULL) {
  444.     return;
  445.     }
  446.  
  447.     /*
  448.      * Translate the coordinates to those of the image, then redisplay it.
  449.      */
  450.  
  451.     Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
  452.         &drawableX, &drawableY);
  453.     Tk_RedrawImage(imgPtr->image, x - imgPtr->header.x1, y - imgPtr->header.y1,
  454.         width, height, drawable, drawableX, drawableY);
  455. }
  456.  
  457. /*
  458.  *--------------------------------------------------------------
  459.  *
  460.  * ImageToPoint --
  461.  *
  462.  *    Computes the distance from a given point to a given
  463.  *    rectangle, in canvas units.
  464.  *
  465.  * Results:
  466.  *    The return value is 0 if the point whose x and y coordinates
  467.  *    are coordPtr[0] and coordPtr[1] is inside the image.  If the
  468.  *    point isn't inside the image then the return value is the
  469.  *    distance from the point to the image.
  470.  *
  471.  * Side effects:
  472.  *    None.
  473.  *
  474.  *--------------------------------------------------------------
  475.  */
  476.  
  477. static double
  478. ImageToPoint(canvas, itemPtr, coordPtr)
  479.     Tk_Canvas canvas;        /* Canvas containing item. */
  480.     Tk_Item *itemPtr;        /* Item to check against point. */
  481.     double *coordPtr;        /* Pointer to x and y coordinates. */
  482. {
  483.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  484.     double x1, x2, y1, y2, xDiff, yDiff;
  485.  
  486.     x1 = imgPtr->header.x1;
  487.     y1 = imgPtr->header.y1;
  488.     x2 = imgPtr->header.x2;
  489.     y2 = imgPtr->header.y2;
  490.  
  491.     /*
  492.      * Point is outside rectangle.
  493.      */
  494.  
  495.     if (coordPtr[0] < x1) {
  496.     xDiff = x1 - coordPtr[0];
  497.     } else if (coordPtr[0] > x2)  {
  498.     xDiff = coordPtr[0] - x2;
  499.     } else {
  500.     xDiff = 0;
  501.     }
  502.  
  503.     if (coordPtr[1] < y1) {
  504.     yDiff = y1 - coordPtr[1];
  505.     } else if (coordPtr[1] > y2)  {
  506.     yDiff = coordPtr[1] - y2;
  507.     } else {
  508.     yDiff = 0;
  509.     }
  510.  
  511.     return hypot(xDiff, yDiff);
  512. }
  513.  
  514. /*
  515.  *--------------------------------------------------------------
  516.  *
  517.  * ImageToArea --
  518.  *
  519.  *    This procedure is called to determine whether an item
  520.  *    lies entirely inside, entirely outside, or overlapping
  521.  *    a given rectangle.
  522.  *
  523.  * Results:
  524.  *    -1 is returned if the item is entirely outside the area
  525.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  526.  *    inside the given area.
  527.  *
  528.  * Side effects:
  529.  *    None.
  530.  *
  531.  *--------------------------------------------------------------
  532.  */
  533.  
  534. static int
  535. ImageToArea(canvas, itemPtr, rectPtr)
  536.     Tk_Canvas canvas;        /* Canvas containing item. */
  537.     Tk_Item *itemPtr;        /* Item to check against rectangle. */
  538.     double *rectPtr;        /* Pointer to array of four coordinates
  539.                  * (x1, y1, x2, y2) describing rectangular
  540.                  * area.  */
  541. {
  542.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  543.  
  544.     if ((rectPtr[2] <= imgPtr->header.x1)
  545.         || (rectPtr[0] >= imgPtr->header.x2)
  546.         || (rectPtr[3] <= imgPtr->header.y1)
  547.         || (rectPtr[1] >= imgPtr->header.y2)) {
  548.     return -1;
  549.     }
  550.     if ((rectPtr[0] <= imgPtr->header.x1)
  551.         && (rectPtr[1] <= imgPtr->header.y1)
  552.         && (rectPtr[2] >= imgPtr->header.x2)
  553.         && (rectPtr[3] >= imgPtr->header.y2)) {
  554.     return 1;
  555.     }
  556.     return 0;
  557. }
  558.  
  559. /*
  560.  *--------------------------------------------------------------
  561.  *
  562.  * ScaleImage --
  563.  *
  564.  *    This procedure is invoked to rescale an item.
  565.  *
  566.  * Results:
  567.  *    None.
  568.  *
  569.  * Side effects:
  570.  *    The item referred to by itemPtr is rescaled so that the
  571.  *    following transformation is applied to all point coordinates:
  572.  *        x' = originX + scaleX*(x-originX)
  573.  *        y' = originY + scaleY*(y-originY)
  574.  *
  575.  *--------------------------------------------------------------
  576.  */
  577.  
  578. static void
  579. ScaleImage(canvas, itemPtr, originX, originY, scaleX, scaleY)
  580.     Tk_Canvas canvas;            /* Canvas containing rectangle. */
  581.     Tk_Item *itemPtr;            /* Rectangle to be scaled. */
  582.     double originX, originY;        /* Origin about which to scale rect. */
  583.     double scaleX;            /* Amount to scale in X direction. */
  584.     double scaleY;            /* Amount to scale in Y direction. */
  585. {
  586.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  587.  
  588.     imgPtr->x = originX + scaleX*(imgPtr->x - originX);
  589.     imgPtr->y = originY + scaleY*(imgPtr->y - originY);
  590.     ComputeImageBbox(canvas, imgPtr);
  591. }
  592.  
  593. /*
  594.  *--------------------------------------------------------------
  595.  *
  596.  * TranslateImage --
  597.  *
  598.  *    This procedure is called to move an item by a given amount.
  599.  *
  600.  * Results:
  601.  *    None.
  602.  *
  603.  * Side effects:
  604.  *    The position of the item is offset by (xDelta, yDelta), and
  605.  *    the bounding box is updated in the generic part of the item
  606.  *    structure.
  607.  *
  608.  *--------------------------------------------------------------
  609.  */
  610.  
  611. static void
  612. TranslateImage(canvas, itemPtr, deltaX, deltaY)
  613.     Tk_Canvas canvas;            /* Canvas containing item. */
  614.     Tk_Item *itemPtr;            /* Item that is being moved. */
  615.     double deltaX, deltaY;        /* Amount by which item is to be
  616.                      * moved. */
  617. {
  618.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  619.  
  620.     imgPtr->x += deltaX;
  621.     imgPtr->y += deltaY;
  622.     ComputeImageBbox(canvas, imgPtr);
  623. }
  624.  
  625. /*
  626.  *----------------------------------------------------------------------
  627.  *
  628.  * ImageChangedProc --
  629.  *
  630.  *    This procedure is invoked by the image code whenever the manager
  631.  *    for an image does something that affects the image's size or
  632.  *    how it is displayed.
  633.  *
  634.  * Results:
  635.  *    None.
  636.  *
  637.  * Side effects:
  638.  *    Arranges for the canvas to get redisplayed.
  639.  *
  640.  *----------------------------------------------------------------------
  641.  */
  642.  
  643. static void
  644. ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
  645.     ClientData clientData;        /* Pointer to canvas item for image. */
  646.     int x, y;                /* Upper left pixel (within image)
  647.                      * that must be redisplayed. */
  648.     int width, height;            /* Dimensions of area to redisplay
  649.                      * (may be <= 0). */
  650.     int imgWidth, imgHeight;        /* New dimensions of image. */
  651. {
  652.     ImageItem *imgPtr = (ImageItem *) clientData;
  653.  
  654.     /*
  655.      * If the image's size changed and it's not anchored at its
  656.      * northwest corner then just redisplay the entire area of the
  657.      * image.  This is a bit over-conservative, but we need to do
  658.      * something because a size change also means a position change.
  659.      */
  660.  
  661.     if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth)
  662.         || ((imgPtr->header.y2 - imgPtr->header.y1) != imgHeight)) {
  663.     x = y = 0;
  664.     width = imgWidth;
  665.     height = imgHeight;
  666.     Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,
  667.         imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);
  668.     } 
  669.     ComputeImageBbox(imgPtr->canvas, imgPtr);
  670.     Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,
  671.         imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),
  672.         (int) (imgPtr->header.y1 + y + height));
  673. }
  674.